package itsm.isperp.workflow.web.controller;

import itsm.isperp.framework.core.context.ContextHolder;
import itsm.isperp.framework.data.domain.PageResponse;
import itsm.isperp.framework.domain.BaseBean;
import itsm.isperp.framework.domain.IBean;
import itsm.isperp.framework.domain.IUser;
import itsm.isperp.framework.utils.Pair;
import itsm.isperp.framework.web.request.JqGridRequest;
import itsm.isperp.framework.web.response.ResultMessage;
import itsm.isperp.module.entity.app.AppDict;
import itsm.isperp.module.entity.bpm.BpmProcessRelation;
import itsm.isperp.module.entity.bpm.act.ActRuTask;
import itsm.isperp.module.service.app.AppDictService;
import itsm.isperp.module.service.bpm.BpmProcessRelationService;
import itsm.isperp.module.service.bpm.act.ActRuTaskService;
import itsm.isperp.workflow.dto.BpmTransitionLine;
import itsm.isperp.workflow.graph.Node;
import itsm.isperp.workflow.service.BpmProcessRunService;

import java.io.IOException;
import java.sql.SQLException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.dom4j.DocumentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

/**
 * 
 * 运行流程的控制器
 * 
 * @author lizx
 * @date 2013-6-28
 * 
 */
@Controller
@RequestMapping("workflow/processRun")
public class ProcessRunController {

	@Autowired
	BpmProcessRunService bpmProcessRunService;

	@Autowired
	ActRuTaskService actRuTaskService;

	@RequestMapping(value = "view")
	public String view(String processKey, String id, String from,
			HttpServletRequest req, RedirectAttributes redirectAttributes)
			throws Exception {
		String pcontrolid = req.getParameter("pcontrolid");
		String projectId = req.getParameter("projectId");

		String formUrl = this.bpmProcessRunService.view(id, processKey);
		redirectAttributes.addAttribute("id", id);
		redirectAttributes.addAttribute("pcontrolid", pcontrolid);
		redirectAttributes.addAttribute("projectId", projectId);
		return "redirect:/" + formUrl;
	}

	@RequestMapping(value = "entry")
	public String entry(String processKey, String id, String from,
			HttpServletRequest req, RedirectAttributes redirectAttributes)
			throws Exception {

		String pcontrolid = req.getParameter("pcontrolid");
		String projectId = req.getParameter("projectId");
		String fromId = req.getParameter("fromId");
		String fromProcessKey = req.getParameter("fromProcessKey");

		String formUrl = this.bpmProcessRunService.entry(id, processKey, from);

		if (StringUtils.isEmpty(formUrl)) {
			redirectAttributes
					.addAttribute("msg", "表单未设定！可能的原因是：流程/流程节点表单未定义。");
			return "redirect:/system/errorInfo";

		}

		redirectAttributes.addAttribute("id", id);
		redirectAttributes.addAttribute("pcontrolid", pcontrolid);
		redirectAttributes.addAttribute("projectId", projectId);
		redirectAttributes.addAttribute("fromId", fromId);
		redirectAttributes.addAttribute("fromProcessKey", fromProcessKey);
		return "redirect:/" + formUrl;
	}

	@RequestMapping(value = "entryProcess")
	public String entryProcess(String processKey, String processId,
			String from, HttpServletRequest req,
			RedirectAttributes redirectAttributes) {

		String pcontrolid = req.getParameter("pcontrolid");
		String projectId = req.getParameter("projectId");

		IBean idBean = new BaseBean();
		String formUrl = this.bpmProcessRunService.entryProcess(idBean,
				processId, processKey, from);
		if (StringUtils.isEmpty(formUrl)) {
			redirectAttributes
					.addAttribute("msg", "表单未设定！可能的原因是：流程/流程节点表单未定义。");
			return "redirect:/system/errorInfo";

		}
		redirectAttributes.addAttribute("id", idBean.getId());
		redirectAttributes.addAttribute("pcontrolid", pcontrolid);
		redirectAttributes.addAttribute("projectId", projectId);
		return "redirect:/" + formUrl;
	}

	/**
	 * 取得下一步的处理按钮
	 * 
	 * @param key
	 *            流程定义的关键字
	 * 
	 * @param taskId
	 *            流程任务实例的id
	 * @return
	 */
	@ResponseBody
	@RequestMapping("getNextSteps")
	public List<BpmTransitionLine> getNextSteps(String key, String processId) {
		return bpmProcessRunService.getNextSteps(key, processId,
				ContextHolder.getLoginUsername());
	}

	/**
	 * 进入下一个流程节点
	 * 
	 * @param taskId
	 *            下一个步骤的taskId
	 * @param name
	 * @throws SQLException
	 */
	@ResponseBody
	@RequestMapping("gotoNextStep")
	public ResultMessage gotoNextStep(String key, String nextTaskId,
			String nextTransitionId, String processId, String businessKey,
			String name, String username, String suggestion,
			Integer processMode, Integer commitType, String fromId,
			String fromProcessKey) throws Exception {
		processMode = processMode == null ? 0 : processMode;

		if (StringUtils.isNotEmpty(fromId)) {

			// 根据此fromProcessKey获取到所在实体，然后创建一条数据，并且为此数据赋值
			BpmProcessRelationService bpmProcessRelationService = ContextHolder
					.getSpringBean("bpmProcessRelationService");
			BpmProcessRelation br = new BpmProcessRelation();
			br.setFromId(fromId);
			br.setToId(businessKey);
			br.setFromType(fromProcessKey);
			br.setToType(key);

			bpmProcessRelationService.saveOrUpdate(br, null);

		}

		Pair<String, List<Map<String, Object>>> result = this.bpmProcessRunService
				.gotoNextSetp(key, nextTaskId, nextTransitionId, processId,
						businessKey, username, suggestion, processMode,
						commitType);

		if (result == null || result.getRightObject() == null
				|| result.getRightObject().size() == 0) {
			return ResultMessage.success("流程结束");
		}
		StringBuilder nextUser = new StringBuilder();
		List<Map<String, Object>> list = result.getRightObject();
		int i = list.size();
		if (i > 0) {
			nextUser.append(list.get(0).get("fullname")).append("(")
					.append(list.get(0).get("name")).append(")");
		}
		for (int j = 1; j < i; j++) {
			Map<String, Object> m = list.get(j);
			if (m != null)
				nextUser.append(",").append(m.get("fullname")).append("(")
						.append(m.get("name")).append(")");
		}

		return ResultMessage.success(result.getLeftObject() + ":"
				+ nextUser.toString());
	}

	/**
	 * 输出跟踪流程信息
	 * 
	 * @param processInstanceId
	 * @return
	 * @throws DocumentException
	 * @throws IOException
	 */
	@RequestMapping(value = "traceView")
	public ModelAndView traceView(String processId) throws IOException,
			DocumentException {

		ModelAndView mv = new ModelAndView("workflow/processRun/traceView");

		mv.addObject("shapeMeta",
				bpmProcessRunService.traceShapeMeta(processId));
		Map<String, Object> map = bpmProcessRunService.trace(processId);
		mv.addAllObjects(map);
		mv.addObject("processId", processId);
		return mv;

	}

	/**
	 * 获取流程跟踪图
	 * 
	 * @param processInstanceId
	 *            流程实例Id
	 * @param response
	 *            数据响应
	 * @throws ServletException
	 *             服务端异常
	 * @throws IOException
	 *             IO异常
	 */
	@RequestMapping(value = "traceImage/{processId}")
	public void traceImage(@PathVariable("processId") String processId,
			HttpServletResponse response) throws ServletException, IOException {
		byte[] b = this.bpmProcessRunService.traceImage(processId);
		response.getOutputStream().write(b);
	}

	/**
	 * 所有任务
	 * 
	 * @param req
	 * @return
	 */
	@RequestMapping(value = "allProcessManage")
	public ModelAndView allProcessManage(JqGridRequest req) {
		return new ModelAndView("workflow/processRun/allProcessManage");
	}

	@RequestMapping(value = "allProcessList")
	@ResponseBody
	public PageResponse<Map<String, Object>> allProcessList(JqGridRequest req) {

		return this.bpmProcessRunService.findProcess(req).toPage();
	}

	/**
	 * 所有任务
	 * 
	 * @param req
	 * @return
	 */
	@RequestMapping(value = "allTaskManage")
	public ModelAndView allTaskManage(JqGridRequest req) {
		return new ModelAndView("workflow/processRun/allTaskManage");
	}

	/**
	 * 所有任务列表
	 * 
	 * @param req
	 * @return
	 */
	@RequestMapping(value = "allTaskList")
	@ResponseBody
	public Page<ActRuTask> allTaskList(JqGridRequest req) {
		return actRuTaskService.findTaskListByRequest(req).toPage();
	}

	@RequestMapping(value = { "myTaskManage", "myTaskListView" })
	public ModelAndView myTaskManage(HttpServletRequest req) {

		ModelAndView mv = new ModelAndView("workflow/processRun/myTaskManage");

		mv.addObject("username", req.getParameter("username"));
		return mv;
	}

	/**
	 * 所有任务列表
	 * 
	 * @param req
	 * @return
	 */
	@RequestMapping(value = "myTaskList")
	@ResponseBody
	public List<Map<String, Object>> myTaskList(String username,
			JqGridRequest req) {

		if (StringUtils.isEmpty(username)) {
			username = ContextHolder.getLoginUsername();
		}

		req.setSelectColumns(null);
		List<Map<String, Object>> l = bpmProcessRunService.getAllTodoList(
				username, req);

		return l;
	}

	/**
	 * 终结流程
	 * 
	 * @param processId
	 * @param suggestion
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "endProcess")
	@ResponseBody
	public ResultMessage endProcess(String processId, String suggestion)
			throws Exception {

		return ResultMessage.newInstance(bpmProcessRunService.endProcess(
				ContextHolder.getLoginUsername(), processId, suggestion));
	}

	/**
	 * 删除流程
	 * 
	 * @param processId
	 * @param suggestion
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "deleteProcess")
	@ResponseBody
	public ResultMessage deleteProcess(String processId, String suggestion)
			throws Exception {
		bpmProcessRunService.deleteProcessInstance(processId,
				ContextHolder.getLoginUsername());
		return ResultMessage.success();
		// JdbcTemplate jdbcTemplate =
		// ContextHolder.getSpringBean("jdbcTemplate");
		// String sql = "select proc_inst_id_ from("
		// +
		// "select proc_inst_id_,business_key_ from act_ru_execution  where business_key_ in( "
		// +
		// "select business_key_ from    (select business_key_,count(business_key_) c_business_key_  from act_ru_execution  "
		// + "group by business_key_) where c_business_key_>1))t  and processKey=''  " + ""
		// + "inner join  icd_incident b on t.business_key_=b.id  " + ""
		// + "and b.process_id<>t.proc_inst_id_";
		// List<String> ss = jdbcTemplate.queryForList(sql, String.class);
		//
		// for (String s : ss) {
		// bpmProcessRunService.deleteProcessInstance(s, "admin");
		// }

	}

	/**
	 * 流程审批控制--审批并进入下一步
	 * 
	 * @param key
	 *            流程key
	 * @param taskId
	 *            任务id
	 * @param processInstanceId
	 *            流程实体id
	 * @param businessKey
	 *            业务表的id
	 * @param name
	 *            步骤下一步连接线名称
	 * @param username
	 *            下一步处理人
	 * @param common
	 *            处理意见
	 * @return
	 * @throws SQLException
	 */
	@RequestMapping(value = "approvalEdit")
	public ModelAndView approvalEdit(String key, String nextTaskId,
			String nextTransitionId, String processId, String businessKey,
			String name, int processMode, String commitType, String fromId,
			String fromProcessKey, HttpServletRequest req) throws SQLException {
		// 用户的列表
		String pcontrolid = req.getParameter("pcontrolid");
		ModelAndView mv = new ModelAndView("workflow/processRun/approvalEdit");
		mv.addObject("processKey", key);
		mv.addObject("nextTaskId", nextTaskId);
		mv.addObject("nextTransitionId", nextTransitionId);
		mv.addObject("processId", processId);
		mv.addObject("businessKey", businessKey);
		mv.addObject("name", name);
		mv.addObject("processMode", processMode);
		mv.addObject("commitType", commitType);
		mv.addObject("fromId", fromId);
		mv.addObject("fromProcessKey", fromProcessKey);

		if (StringUtils.isEmpty(pcontrolid)) {
			mv.addObject("pcontrolid", "");
		} else {

			mv.addObject("pcontrolid", pcontrolid);
		}

		Collection<IUser> users = bpmProcessRunService.getNextSetpUser(key,
				processId, nextTaskId, businessKey,
				ContextHolder.getLoginUsername(), processMode);

		List<IUser> ul = new ArrayList<>();
		ul.addAll(users);
		Collections.sort(ul, new Comparator<IUser>() {
			@Override
			public int compare(IUser o1, IUser o2) {
				// 根据用户汉字姓名排序
				return Collator.getInstance(java.util.Locale.CHINA).compare(
						o1.getFullname(), o2.getFullname());

			}

		});

		mv.addObject("users", ul);
		if (ul.size() > 8) {
			mv.addObject("searchCls", "search");

		}
		String userNames="";
		for(IUser u:ul)
		{
			userNames+=u.getUsername()+",";
		}
		if(userNames.length()>0)
		{
			userNames=userNames.substring(0,userNames.length()-1);
			mv.addObject("userNames", userNames);
		}
		

		AppDictService appDictService = ContextHolder
				.getSpringBean("appDictService");

		List<AppDict> views = appDictService.findByType("BPM_COMMONS");

		mv.addObject("views", views);

		return mv;
	}
	
	//节点提交选择人，在某些情况下 由于流程有判断节点，不能弹窗选择处理人，用此方法临时代替，1.弹窗选择处理人写入字段 2.流程处理选择账号处理
	@RequestMapping(value = "beginSubEdit")
	public ModelAndView beginSubEdit(HttpServletRequest req) throws SQLException {
		// 用户的列表
		String categoryId = req.getParameter("categoryId");
		String sql="select description from app_dict where type_code='ICD_FIRSTSTEP_SUPPORTERS' AND code='"+categoryId+"'";
		JdbcTemplate jdbcTemplate = ContextHolder.getSpringBean("jdbcTemplate");
		AppDictService appDictService = ContextHolder.getSpringBean("appDictService");
		String filter=jdbcTemplate.queryForObject(sql, String.class);
		String sql1 = "select name,fullname from (SELECT b.name,b.fullname,a.name role_name FROM v_app_user_role a INNER JOIN app_user b ON a.app_user_name=b.name) t where 1=1 "+filter;
	    List<Map<String,Object>> list=jdbcTemplate.queryForList(sql1);
	    String userNames="";
	    for(Map<String,Object> m:list)
	    {
	    	String tm=m.get("name").toString();
	    	userNames+=tm+",";
	    }
	    userNames=userNames.substring(0,userNames.length()-1);
	    ModelAndView mv = new ModelAndView("workflow/processRun/beginSubEdit");
		mv.addObject("userNames", userNames);
		List<AppDict> views = appDictService.findByType("BPM_COMMONS");
		mv.addObject("views", views);
		return mv;
	}

	// ~---------------------------------转派----------------------------------------～//
	@RequestMapping(value = "transferAssigneeEdit")
	public ModelAndView transferAssigneeEdit(String processId) {

		ModelAndView mv = new ModelAndView(
				"workflow/processRun/transferAssigneeEdit");
		mv.addObject("processId", processId);
		return mv;
	}

	@RequestMapping(value = "transferAssignee")
	@ResponseBody
	public ResultMessage transferAssignee(String processId, String username,
			String suggestion) {
		String exeUsername = ContextHolder.getLoginUsername();
		this.bpmProcessRunService.transferAssignee(processId, exeUsername,
				username, suggestion);
		return ResultMessage.success();
	}

	// ~--------------------------------end转派--------------------------------------～//

	// ~---------------------------------转派----------------------------------------～//
	@RequestMapping(value = "jumptoEdit")
	public ModelAndView jumptoEdit(String processId) {

		ModelAndView mv = new ModelAndView("workflow/processRun/jumptoEdit");

		JdbcTemplate jdbcTemplate = ContextHolder.getSpringBean("jdbcTemplate");
		jdbcTemplate.update(
				"DELETE FROM act_ru_identitylink where proc_inst_id_=?",
				processId);
		List<Node> nodes = this.bpmProcessRunService
				.getUserTaskByProcessInstanceId(processId);
		mv.addObject("nodes", nodes);

		mv.addObject("processId", processId);

		// AppLogActionService appLogActionService = ContextHolder
		// .getSpringBean("appLogActionService");
		//
		// JqGridRequest reqs = new JqGridRequest();
		// reqs.isPageable(false);
		// reqs.setSort("CREATE_TIME", Direction.ASC);
		// reqs.addFilterRule("module_name", JqGridFilterRuleOp.eq,
		// "icd_incident");
		// reqs.addFilterRule("description", JqGridFilterRuleOp.cn,
		// "confirmtimemanId");
		//
		// List<AppLogAction> logs = appLogActionService.findAll(reqs);
		//
		// StringBuilder sb = new StringBuilder();
		// for (AppLogAction action : logs) {
		//
		// String s = action.getDescription();
		// IcdIncident icd = JsonBuilder.buildNormalBinder().fromJson(s,
		// IcdIncident.class);
		//
		// sb.append("UPDATE icd_incident SET confirmtimeman_Id='"
		// + icd.getConfirmtimemanId() + "',confirmtimeman_name='"
		// + icd.getConfirmtimemanName() + "' WHERE id='"
		// + icd.getId() + "'");
		//
		// }

		return mv;
	}

	/**
	 * 
	 * 
	 * 
	 * @param processId
	 * @param actNodeId
	 * @param suggestion
	 * @return
	 */
	@RequestMapping(value = "jumpto")
	@ResponseBody
	public ResultMessage jumpto(String processId, String actNodeId,
			String suggestion) {
		String username = ContextHolder.getLoginUsername();
		this.bpmProcessRunService.jumpto(processId, actNodeId, username,
				suggestion);
		return ResultMessage.success();
	}

	// ~--------------------------------end转派--------------------------------------～//

	@RequestMapping(value = "reOpenProcess")
	@ResponseBody
	public ResultMessage reOpenProcess(String processId, String username,
			String suggestion) {
		try {
			this.bpmProcessRunService.reOpenProcess(processId);
		} catch (Exception ex) {
			return ResultMessage.failure(ex);
		}
		return ResultMessage.success();
	}
}
